﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using ProgNetComponents.Validation.Design;
using System.Drawing.Design;
using ProgNetComponents.Design.Attributes;

namespace ProgNetComponents.Validation.Rules
{
    /// <summary>
    /// Multiple validation rules
    /// </summary>
    public abstract class MultiValidationRule : ValidationRule, IDataValidationRule, IStopOnFirstErrorValidationRule
    {
        #region Members
        /// <summary>
        /// The rules
        /// </summary>
        private List<ColumnValidationRule> _Rules = new List<ColumnValidationRule>();
        /// <summary>
        /// The data source
        /// </summary>
        private System.Data.DataTable _DataSource;
        /// <summary>
        /// The column
        /// </summary>
        private string _Column;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the rules.
        /// </summary>
        /// <value>
        /// The rules.
        /// </value>
        protected List<ColumnValidationRule> Rules { get {  return _Rules; } }

        /// <summary>
        /// Gets or sets a value indicating whether [stop on first error].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [stop on first error]; otherwise, <c>false</c>.
        /// </value>
        public bool StopOnFirstError
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the column.
        /// </summary>
        /// <value>
        /// The column.
        /// </value>
        [Editor(typeof(IDataValidationRuleColumnNameEditor), typeof(UITypeEditor))]
        public string Column
        {
            get { return _Column; }
            set
            {
                _Column = value;
                if (Rules != null)
                {
                    foreach (var r in Rules)
                        r.Column = value;
                }
            }
        }
        #endregion

        #region CTOR
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiValidationRule"/> class.
        /// </summary>
        protected MultiValidationRule()
        {
            
        }

        #endregion
        /// <summary>
        /// Clears the validation settings.
        /// </summary>
        public override void ClearValidationSettings()
        {
            base.ClearValidationSettings();
            foreach (var r in Rules)
                r.ClearValidationSettings();
        }
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="T:System.ComponentModel.Component" /> and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (Rules != null)
                {
                    foreach (var r in Rules)
                        r.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// Adds the rule.
        /// </summary>
        /// <param name="r">The r.</param>
        protected void AddRule(ColumnValidationRule r)
        {
            Rules.Add(r);
        }

        /// <summary>
        /// Does the validate.
        /// </summary>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        protected override bool DoValidate(System.Data.DataRow row)
        {
            bool result = true;
            if (Rules != null)
            {
                foreach (var r in Rules)
                {
                    result &= r.ValidateRow(row);
                    if (!result && StopOnFirstError)
                        return result;
                }
            }
            return result;
        }

        /// <summary>
        /// Called when [validation failed].
        /// </summary>
        /// <param name="row">The row.</param>
        protected override void OnValidationFailed(System.Data.DataRow row)
        {

        }

        /// <summary>
        /// Gets or sets the data source.
        /// </summary>
        /// <value>
        /// The data source.
        /// </value>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        System.Data.DataTable IDataValidationRule.DataSource
        {
            get { return _DataSource; }
            set
            {
                _DataSource = value;
                if (Rules != null)
                {
                    foreach (var r in Rules)
                    {
                        if (r is IDataValidationRule)
                        {
                            ((IDataValidationRule)r).DataSource = value;
                        }
                    }
                }
            }
        }

    }
}
